using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;

using IronPython.Hosting;
using IronPython.Compiler;

using WeifenLuo.WinFormsUI.Docking;
using System.Xml;
using SystemsBiologyWorkbench = SBW;

using Athena.Tools;

namespace Athena
{
    public partial class ScriptingHost : IGUITool
    {
        private Stream oStream;
        private PythonEngine engine;

        List<string> _oCommandBuffer = new List<string>();
        int _nCurrentPos = -1;

        #region Initialize ScriptPlugin

        public override void SetupToolStrip(ToolStrip oStrip)
        {
            ToolStripButton oButton = new ToolStripButton();
            oButton.Text = Text;
            oButton.ToolTipText = "Script access to the object model via IronPython";
            oButton.Click += new EventHandler(ShowHide_Click);
            oStrip.Items.Add(oButton);
        }

        public override void SetupDockPanel(WeifenLuo.WinFormsUI.Docking.DockPanel oPanel)
        {
            this.DockPanel = oPanel;
        }
        public override void ShowHide_Click(object sender, EventArgs e)
        {
            if (IsHidden)
            {
                //DockState = DockState.DockBottom;
                Show();
            }
            else
            {
                Hide();
            }
        }

        public ScriptingHost()
        {
            _bRequiresNewToolWindow = true;
            Text = "Script &Console";
            InitializeComponent();
            InitializePythonEngine();
            ToolManager.Instance.RegisterTool(Text, "Script access to the object model via IronPython", this);
        }
        #endregion

        void InitializePythonEngine()
        {
            try
            {
                oStream = new MemoryStream();
                engine = new PythonEngine();
                engine.AddToPath(Application.ExecutablePath);

                engine.Import("Site");
                engine.Import("clr");
                engine.Import("Athena");
                engine.Import("Athena.Tools");
                engine.Import("Athena.Core");
                engine.Import("Athena.Objects");
                engine.Import("Athena.Functions");
                engine.Import("System");

                engine.SetStandardError(oStream);
                engine.SetStandardOutput(oStream);

                engine.Globals["model"] = Program.Model;
                engine.Globals["panel"] = Utility.DrawPanel;
                engine.Globals["util"] = new Athena.Utility();
                engine.Globals["plugin"] = PluginManager.Instance;
                engine.Globals["tool"] = ToolManager.Instance;
                engine.Globals["sim"] = new SBW.SBWSimulator("edu.kgi.roadRunner", "sim"); //ToolManager.Instance.Simulator;
                engine.Globals["sbw"] = new SystemsBiologyWorkbench.Broker();  //new SystemsBiologyWorkbench.Module("BROKER");
            }
            catch (Exception)
            {
            }
            if (scriptControl1 != null)
            {
                scriptControl1.Engine = engine;
                scriptControl1.Stream = oStream;
            }
        }
      

        public void ExecuteCommand(string sCommand)
        {
            try
            {
                engine.ExecuteToConsole(sCommand);
            }
            catch (Exception)
            {
            }
        }


        private void cmdExecute_Click(object sender, EventArgs e)
        {
            string sCommand = txtCommand.Text;

            try
            {
                

                if (sCommand == "") return;

                long nCurrent = oStream.Position;
                txtHistory.Text += Environment.NewLine + Environment.NewLine + ">>> " + sCommand + Environment.NewLine + ">>> ";
                engine.ExecuteToConsole(sCommand);
                _nCurrentPos = -1;
                if (!_oCommandBuffer.Contains(sCommand))
                    _oCommandBuffer.Add(sCommand);
                txtCommand.Text = "";

                oStream.Position = nCurrent;

                StreamReader oTemp = new StreamReader(oStream);
                string sText = oTemp.ReadToEnd();
                if (sText == "")
                {
                    ScrollToEnd();
                    return;
                }
                txtHistory.Text += sText;
                txtHistory.Text += Environment.NewLine;
            }
            catch (Exception ex)
            {
                txtHistory.Text += Environment.NewLine + Environment.NewLine + "Error: " + ex.Message;
            }
            ScrollToEnd();
        }
        private void ScrollToEnd()
        {
            ScrollToEnd(txtHistory);
            txtCommand.Focus();
        }
        private void ScrollToEnd(TextBoxBase oControl)
        {
            oControl.Focus();
            oControl.SelectionLength = 0;
            oControl.SelectionStart = txtHistory.Text.Length;
            oControl.ScrollToCaret();
        }
        private void SetCommand(int nPos)
        {
            if (nPos < 0 || (nPos >= _oCommandBuffer.Count))
            {
                _nCurrentPos = -1;
                return;
            }
            else
            {
                txtCommand.Text = _oCommandBuffer[nPos];
                _nCurrentPos = nPos;
                ScrollToEnd(txtCommand);
            }

        }
        private void txtCommand_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                    SetCommand(_nCurrentPos + 1);
                    break;
                case Keys.Down:
                    SetCommand(_nCurrentPos - 1);
                    break;
                default:
                    break;
            }


        }
    }
}
